import tensorflow as tf
import numpy as np
# pyplot是类似matlab的绘图api
import matplotlib.pyplot as plt

print(tf.__version__)
# 从tf官方获取数据集，这一行会自动将数据下载下来并缓存
fashion_mnist = tf.keras.datasets.fashion_mnist
# 加载数据集，其中train_images是6w大小的数组，每个元素又是28*28的二维int数组，这个二维数组表示一副图像，train_labels也是6w大小的数组，与图像对应表示每个图像是什么分类
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

class_names = ['T恤/上衣', '裤子', '套衫', '裙子', '外套', '凉鞋', '衬衫', '运动鞋', '包', '鞋子']

# plt.figure()
# plt.imshow(train_images[0])
# plt.colorbar()
# plt.grid(False)
# plt.show()

# train_labels = train_labels % 2
# test_labels = test_labels % 2

train_images = train_images / 255.0
test_images = test_images / 255.0

# plt.figure(figsize=(10,10))
# for i in range(25):
#     plt.subplot(5,5,i+1)
#     plt.xticks([])
#     plt.yticks([])
#     plt.grid(False)
#     plt.imshow(train_images[i], cmap=plt.cm.binary)
#     plt.xlabel(class_names[train_labels[i]], fontdict={'family':'simhei'})
# plt.show()

# 声明一个模型
model = tf.keras.Sequential([
    # 第一层将输入的28*28的二维数组图像展开为一维，即变成28*28=768大小的一位数组，因为模型的输入必须是一维的
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    # 第二层处理数据，第一个参数为节点数量（神经元），activation为激活函数，具体作用还没看，文档https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dense
    tf.keras.layers.Dense(256, activation='relu'),
    # 最后一层为输出层，因为要输出模型对10种分类每种的预测概率，所以节点数量为10
    tf.keras.layers.Dense(10)
])
# 编译模型，三个参数都有用，还没看
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
# 训练模型，train_labels中的值不仅表示数组下标，还起到告诉模型对应输入应该增大哪个输出节点的权重，与输出层节点一一对应，epochs为循环次数
model.fit(train_images, train_labels, epochs=1)
# 测试模型，verbose参数不影响模型
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)

print('\nTest accuracy:', test_acc)
# 在之前的模型基础上再加一层输出层，如果不加这一层，预测值都是相对值，加上之后会按比例计算为百分比
probability_model = tf.keras.Sequential([model,
                                         tf.keras.layers.Softmax()])
# 预测所有测试图片的标签
# predictions = model.predict(test_images)
predictions = probability_model.predict(test_images)
# 下面都是显示结果的代码
num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))

# python的函数可以任意调用前定义
def plot_image(i, predictions_array, true_label, img):
  true_label, img = true_label[i], img[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])

  plt.imshow(img, cmap=plt.cm.binary)
  #plt.imshow(img)

  predicted_label = np.argmax(predictions_array)
  if predicted_label == true_label:
    color = 'blue'
  else:
    color = 'red'

  plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                100*np.max(predictions_array),
                                class_names[true_label]),
                                color=color, fontdict={'family':'simhei'})

def plot_value_array(i, predictions_array, true_label):
  true_label = true_label[i]
  plt.grid(False)
  plt.xticks(range(10))
  plt.yticks([])
  thisplot = plt.bar(range(10), predictions_array, color="#777777")
  plt.ylim([0, 1])
  predicted_label = np.argmax(predictions_array)

  thisplot[predicted_label].set_color('red')
  thisplot[true_label].set_color('blue')

for i in range(num_images):
  plt.subplot(num_rows, 2*num_cols, 2*i+1)
  plot_image(i, predictions[i], test_labels, test_images)
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plot_value_array(i, predictions[i], test_labels)
plt.tight_layout()
plt.show()